package com.gitee.jmliu1983.analysis;

//import java.sql.Date;

import java.util.Date;
//
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson2.JSONObject;

/**
 * @author jianmin.liu <br>
 *         当给定了几页按时间顺序排列的数据，包含一个参数列，通过本类可以获取参数变化时的时间点<br>
 *         使用方法：<br>
 * 
 *         1. 设定数据合并器的配置：<code> merger.setConf("spot_drawing", "datetime", "current","yyyy-MM-dd HH:mm:ss");</code><br>
 * 
 *         2. 喂数据： <code>merger.feedItems(spotsPage1);</code><br>
 * 
 *         3. 获取结果：<code>merger.getFinalMergedResult();</code><br>
 */
public class ParamHistoryMerger {

	private static ParamHistoryMerger self = null;

	/**
	 * 各页中参数设定起止时间的列表，没有合并的
	 */
	private List<JSONObject> timeLineNotMerged = new ArrayList<JSONObject>();

	/**
	 * 各页中参数设定起止时间的列表，合并的，这是最终结果
	 */
	private List<JSONObject> timeLineMerged = new ArrayList<JSONObject>();

	/**
	 * 保存各个group的上一个参数，用来判断这个参数是否发生变化，多页多次使用，所以放在类里面
	 */
	private Map<String, String> lastParam = new HashMap<String, String>();

	private SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	private String groupField; // 分组字段
	private String timeField; // 时间字段
	private String paramField; // 参数字段
	private String timeFmt; // 时间格式化字符串

	public static ParamHistoryMerger getInstance() {
		if (self == null)
			self = new ParamHistoryMerger();
		return self;
	}

	/**
	 * 按照时间顺序排序
	 * 
	 * @param items
	 * @return
	 */
	private List<JSONObject> sortItems(List<JSONObject> items) {
		// 先根据时间排序
		this.dateParser = new SimpleDateFormat(timeFmt);
		Collections.sort(items, (a, b) -> {
			String aTimeString = a.getString(timeField);
			String bTimeString = b.getString(timeField);

			Date aTime = new Date();
			Date bTime = new Date();
			try {
				aTime = dateParser.parse(aTimeString);
				bTime = dateParser.parse(bTimeString);

			} catch (ParseException e) {
				e.printStackTrace();
			}
			return aTime.compareTo(bTime);
		});
		return items;
	}

	/**
	 * 设定数据的字段
	 * 
	 * @param groupField 分组字段
	 * @param timeField  时间字段
	 * @param paramField 参数字段
	 * @param timeFmt    时间字段的时间格式
	 */
	public void setConf(String groupField, String timeField, String paramField, String timeFmt) {
		this.groupField = groupField;
		this.timeField = timeField;
		this.paramField = paramField;
		this.timeFmt = timeFmt;
	}

	/**
	 * 喂入数据
	 * 
	 * @param items
	 */
	public void feedItems(List<JSONObject> items) {
		List<JSONObject> sortedItems = sortItems(items);
		for (JSONObject jsonObject : sortedItems) {
			String group = jsonObject.getString(groupField);
			String time = jsonObject.getString(timeField);
			String param = jsonObject.getString(paramField);

			String paramCompare = lastParam.get(group);
			JSONObject timeLine = new JSONObject();
			timeLine.put("from", time);
			timeLine.put(groupField, group);
			timeLine.put(paramField, param);

			if (paramCompare == null) { // 上一个参数为空，说明这是这个分组的第一个参数
				// 本组的参数
				lastParam.put(group, param);
				timeLineNotMerged.add(timeLine);
			} else {
				if (param.compareTo(paramCompare) == 0)
					continue; // 与上一个参数相同
				else {
					lastParam.put(group, param);
					timeLineNotMerged.add(timeLine);
				}
			}
		}
	};

	/**
	 * 写入时间段的停止时间“To”
	 */
	private void mergeTimeLine() {
		HashMap<String, String> lastDatetime = new HashMap<String, String>(); // 只用一次，所以在方法里面

		for (int i = this.timeLineNotMerged.size() - 1; i >= 0; i--) {
			JSONObject jsonObject = this.timeLineNotMerged.get(i);
			String group = jsonObject.getString(groupField);
			String time = jsonObject.getString("from");

			String paramCompare = lastDatetime.get(group);
			JSONObject timeLine = jsonObject.clone();

			if (paramCompare == null) { // 上一个参数为空，说明这是这个分组的第一个参数
				// 本组的参数
				lastDatetime.put(group, time);
				timeLine.put("to", "");
				timeLineMerged.add(timeLine);
			} else {
				lastDatetime.put(group, time);
				timeLine.put("to", paramCompare);
				timeLineMerged.add(timeLine);
			}

		}
		Collections.reverse(timeLineMerged);
	}

	public void clearTimeLine() {
		this.timeLineMerged.clear();
		this.timeLineNotMerged.clear();
		this.groupField = "";
		this.paramField = "";
		this.timeField = "";
		this.lastParam = new HashMap<String, String>();
	}

	public List<JSONObject> getFinalMergedResult() {
		this.mergeTimeLine();
		return this.timeLineMerged;
	}

}
